package com.summer.controller.appUser;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.summer.controller.BaseController;
import com.summer.entity.*;
import com.summer.mapper.UserHuluDAO;
import com.summer.service.IOrderBorrowService;
import com.summer.service.IUserBankCardInfoService;
import com.summer.service.IUserInfoService;

import com.summer.service.IUserMoneyRateService;
import com.summer.util.*;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用户借款Controller
 */
@Slf4j
@RestController
@RequestMapping("/v1.0/api/app")
public class UserLoanController extends BaseController {

    @Autowired
    private IUserInfoService userInfoService;
    @Resource
    private IOrderBorrowService orderBorrowService;
    @Resource
    private IUserBankCardInfoService userBankCardInfoService;
    @Resource
    private IUserMoneyRateService userMoneyRateService;

    @Resource
    private UserHuluDAO userHuluDAO;
    @Resource
    private RedisUtil redisUtil;
    /**
     * 	to 借款（排除不能借款的状态，获得能够借款的条件，再把允许借款数据带入申请借款的界面,并且存入Redis中做用户提交借款时校验）
     * @param request
     * @return
     * @throws Exception
     */
    @GetMapping("/apply")
    public Object  confirmLoan(HttpServletRequest request,@RequestBody String jsonDate)throws Exception{
        Map<Object, Object> resultflagMap = new HashMap<>(); //返回flag的map
        Map<String,Object> params= JSONObject.parseObject(jsonDate);
        log.info("start invoke UserLoanController  confirmLoan params={}",params.toString());
        Integer applyMoney =(Integer) params.get("applyMoney");//借款金额
        Integer period=(Integer) params.get("period");      //借款期限
        if (StringUtils.isBlank(applyMoney.toString()) || StringUtils.isBlank(period.toString())){
            return new CallBackResult(Constant.RESULT_BAD_STATUS,Constant.PARAM_IS_NOT_BALANK);//任意一个参数为空都不允许继续
        }
        if (applyMoney < Constant.BORROW_LOWEST_MONEY){//目前1.0版本最低借款金额不能低于1000
            return new CallBackResult(Constant.RESULT_BAD_STATUS,"最低借款金额不能低于"+Constant.BORROW_LOWEST_MONEY+"元");
        }
        if (period < Constant.BORROW_LOWEST_PERIOD){//目前1.0版本最低借款期限不能少于7天
            return new CallBackResult(Constant.RESULT_BAD_STATUS,"最低借款期限不能低于"+Constant.BORROW_LOWEST_PERIOD+"天");
        }
        UserInfo userInfo = redisUser(request);
        if (null !=userInfo){
            Map<String, Object> searchParam = new HashMap<>();
            searchParam.put("phone",userInfo.getPhone());
            List<UserInfo> userInfos = userInfoService.findParams(searchParam);
            if (userInfos.size() > Constant.LIST_SIZE_LENTH_ZORE) {
                UserInfo newUserInfo = userInfos.get(0);
                Double apr_Fee =0.0;//总的服务费率
                UserMoneyRate userMoneyRate = userMoneyRateService.findByUserId(userInfo.getId());//查询该用户的借款金额评估信息
                if (null != userMoneyRate){
                    if (applyMoney > (Integer) (userMoneyRate.getMaxAmount()/Constant.DOLLAR_CHANGE_PENNY)){
                        return  new CallBackResult(Constant.RESULT_BAD_STATUS,"借款金额超限，你当前最高可借款金额为"+(userMoneyRate.getMaxAmount()/Constant.DOLLAR_CHANGE_PENNY)+"元");
                    }
                    //服务费率数据库来为：（信审查询费率+账户管理费利率+实际利息利率）
                    apr_Fee =  userMoneyRate.getCreditVet()+userMoneyRate.getAccountManage()+userMoneyRate.getAccrual();
                }else {
                    if (applyMoney > (newUserInfo.getAmountMax()/Constant.DOLLAR_CHANGE_PENNY)){
                        return  new CallBackResult(Constant.RESULT_BAD_STATUS,"借款金额超限，你当前最高可借款金额为"+(newUserInfo.getAmountMax()/Constant.DOLLAR_CHANGE_PENNY)+"元");
                    }
                    apr_Fee =  Constant.APR_FEE;//服务费（如果UserMoneyRate表里没有该用户的信息）默认按这个平台配置传进来的可借额度的0.3计算服务费
                }
                if (applyMoney > (newUserInfo.getAmountAvailable()/Constant.DOLLAR_CHANGE_PENNY)  ){//大于信用金额，不允许
                    return  new CallBackResult(Constant.RESULT_BAD_STATUS,"你当前剩余额度不足"+applyMoney+"元");
                }
                if (newUserInfo.getAuthenticStatus() == Constant.AUTHENTIC_COMPLETED_STATUS){//用户认证状态为2 表示全部认证完成（包括：个人信息认证状态、紧急联系人认证状态、运营商认证认证状态、芝麻信用认证状态）
                    //继续判断是否绑定啦银行卡
                    Map<String,Object> findCardParam=new HashMap<String,Object>();
                    findCardParam.put("userId",newUserInfo.getId());
                    List<UserBankCardInfo> UserBankCardInfos = userBankCardInfoService.findByParams(findCardParam);//查询用户的银行卡
                    if (UserBankCardInfos.size() > Constant.LIST_SIZE_LENTH_ZORE){//绑定了银行卡
                        UserBankCardInfo userBankCardInfo = UserBankCardInfos.get(0);
                        Map<String,Object> selectOrderMap = new HashMap<>();
                        selectOrderMap.put("userId",newUserInfo.getId());
                        selectOrderMap.put("status",Constant.BORROW_ORDER_REPAYMENT_STATUS);//查询出状态不为10并且不为13的订单
                        List<OrderBorrow> orderBorrows = orderBorrowService.selectByParams(selectOrderMap);
                        if (orderBorrows.size()==Constant.LIST_SIZE_LENTH_ZORE){//没有未在进行中的借款申请订单,允许去申请借款
                            return putResultDate(applyMoney,period,apr_Fee,userBankCardInfo,newUserInfo);
                        }else {//不允许
                            resultflagMap.put("flag","3");//未完成的订单的标记
                            return new CallBackResult(CallBackResult.SUCCESS, "你有未完成的借款,暂时不能再借款");
                        }
                    }else {
                        resultflagMap.put("flag","2");//银行卡未绑定的标记
                        return new CallBackResult(CallBackResult.SUCCESS,"请先绑定银行卡");
                    }
                }else if (newUserInfo.getAuthenticStatus() == Constant.AUTHENTIC_PARTCOMPLETE_STATUS){//部分完成：（继续判断是哪些没有完成）
                    resultflagMap.put("flag","1");//基本信息未完成的标记
                    if (newUserInfo.getRealAuthentic()==Constant.AUTHENTIC_UNCOMPLETED_STATUS){//个人信息实名认证为0
                        return new CallBackResult(CallBackResult.SUCCESS,"未完成个人实名认证",resultflagMap);
                    }
                    if (newUserInfo.getBasicAuthentic()==Constant.AUTHENTIC_UNCOMPLETED_STATUS){//个人信息认证为0
                        return new CallBackResult(CallBackResult.SUCCESS,"未完成个人信息认证",resultflagMap);
                    }
                    if(newUserInfo.getMobileAuthentic()==Constant.AUTHENTIC_UNCOMPLETED_STATUS){//手机运营商认证为0
                        return new CallBackResult(CallBackResult.SUCCESS,"未完成手机运营商认证",resultflagMap);
                    }
                    if (newUserInfo.getEmergencyAuthentic()==Constant.AUTHENTIC_UNCOMPLETED_STATUS){//紧急联系人认证为0
                        return new CallBackResult(CallBackResult.SUCCESS,"未完成紧急联系人认证",resultflagMap);
                    }
                    if (newUserInfo.getZmStatus()==Constant.AUTHENTIC_UNCOMPLETED_STATUS){//芝麻信用认证为0
                        return new CallBackResult(CallBackResult.SUCCESS,"未完成芝麻信用认证",resultflagMap);
                    }
                    if (newUserInfo.getZmIndustyBlack() == Constant.ZM_INDUSTY_BLACK_STATUS ){
                        return new CallBackResult(CallBackResult.SUCCESS,"芝麻行业关注度黑名单",resultflagMap);
                    }
                    UserHulu userHulu = userHuluDAO.selectByUserId(newUserInfo.getId());
                    if (Constant.HULU_AUTH_STATUS==userHulu.getStatus()){//未完成聚信立认证
                        return new CallBackResult(CallBackResult.SUCCESS,"未完成聚信立认证",resultflagMap);
                    }else {
                        return new CallBackResult(Constant.RESULT_BAD_STATUS,"认证信息审核中");
                    }
                }else {
                    return new CallBackResult(CallBackResult.SUCCESS,"请先填写个人信息",resultflagMap);//0或其他状态都属未认证
                }
            }else {
                return new CallBackResult(Constant.RESULT_BAD_STATUS,Constant.USER_MSG_NOT_EXIST);//用户不存在
            }
        }else {
            return new CallBackResult(Constant.RESULT_BAD_STATUS,Constant.USER_MSG_NOT_EXIST);//用户不存在
        }
    }

    /**
     * 借款申请
     * @param request
     * @return
     */
    @PostMapping("/loan")
    public Object loan(HttpServletRequest request,@RequestBody String jsonDate)throws Exception{
        Map<String,Object> params= JSONObject.parseObject(jsonDate);
        log.info("start invoke UserLoanController  loan  JSONStrDate={}",params.toString());
        UserInfo userInfo = redisUser(request);
        Integer applyMoney =(Integer) params.get("applyMoney");
        Integer period=(Integer) params.get("period");
        Integer loanFee=(Integer) params.get("loanFee");
        String payPassword=(String) params.get("payPassword");
        if (StringUtils.isBlank(applyMoney.toString()) || StringUtils.isBlank(period.toString()) || StringUtils.isBlank(loanFee.toString()) || StringUtils.isBlank(payPassword)){
            return new CallBackResult(Constant.RESULT_BAD_STATUS,Constant.PARAM_IS_NOT_BALANK);//任意一个参数为空都不允许继续
        }
        //取出缓存中的借款申请数据
        String redisLoanDataStr = redisUtil.get(Constant.REDIS_LOAN_DATA_PREFIX + userInfo.getPhone() + userInfo.getId());
        if (StringUtils.isBlank(redisLoanDataStr)){
            return new CallBackResult(Constant.RESULT_BAD_STATUS,"缓存借款数据信息为失效，请重新点击借款！");
        }
        Map<String,Object> redisLoanDatas = JSONObject.parseObject(redisLoanDataStr);
        //判断与Redis中达到允许借款的条件的借款数据，不等说明有可能存在恶意改动的行为
        if (!applyMoney.equals((Integer) redisLoanDatas.get("applyMoney"))  || !period.equals((Integer) redisLoanDatas.get("period"))  || !loanFee.equals((Integer)redisLoanDatas.get("loanFee"))  ){
            return new CallBackResult(Constant.RESULT_BAD_STATUS,"借款申请数据有误！");
        }
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("phone",userInfo.getPhone());
        List<UserInfo> userInfos = userInfoService.findParams(map);
        if (userInfos.size() > Constant.LIST_SIZE_LENTH_ZORE){
            UserInfo newUserInfo = userInfos.get(0);
            Map<String, Object> resultPwdStatus = new HashMap<>();
            if ( null == userInfo.getPayPassword()){
                resultPwdStatus.put("payPwdStatus","0");
                return new CallBackResult(-1,"无交易密码",resultPwdStatus);
            }
            Map<String,Object> findCardParam=new HashMap<>();
            findCardParam.put("userId",newUserInfo.getId());
            List<UserBankCardInfo> UserBankCardInfos = userBankCardInfoService.findByParams(findCardParam);//查询用户银行卡信息
            if (UserBankCardInfos.size() > Constant.LIST_SIZE_LENTH_ZORE) {//判断已有银行卡信息
                UserBankCardInfo userBankCardInfo = UserBankCardInfos.get(0);
                if (newUserInfo.getPayPassword().equals(MD5Util.md5(payPassword + newUserInfo.getPayPwdSalt()))){//判断支付密码
                    return saveLoanOrder(newUserInfo,redisLoanDatas,applyMoney,loanFee,period,userBankCardInfo,resultPwdStatus);
                }else {
                    return  new CallBackResult(Constant.RESULT_BAD_STATUS,"交易密码错误");
                }
            }else {
                return  new CallBackResult(Constant.RESULT_BAD_STATUS,"银行卡不存在");
            }
        }else {
                return  new CallBackResult(Constant.RESULT_BAD_STATUS,Constant.USER_MSG_NOT_EXIST);
        }
    }

    /**
     * 允许去借款返回借款界面数据的方法
     * @param applyMoney  //借款金额
     * @param period        //借款期限
     * @param userBankCardInfo  //用户银行卡信息
     * @return
     * @throws Exception
     */
    public Object putResultDate(Integer applyMoney,Integer period,Double apr_Fee,UserBankCardInfo userBankCardInfo,UserInfo userInfo)throws  Exception{
        log.info("start invoke UserLoanController  loan  applyMoney={},period={},userBankCardInfo={}",applyMoney,period,userBankCardInfo.toString());
        Map<String,Object> resultMap=new HashMap<String,Object>();
        resultMap.put("applyMoney",applyMoney);//借款金额
        resultMap.put("period",period);//借款期限
        resultMap.put("apr_Fee",apr_Fee);
        Double loanFee  = (apr_Fee * applyMoney);
        resultMap.put("loanFee",loanFee.intValue());//借款服务费
        resultMap.put("bankName",userBankCardInfo.getBankName());
        resultMap.put("bankNum",userBankCardInfo.getCardNum().substring(userBankCardInfo.getCardNum().length()-4,userBankCardInfo.getCardNum().length()));//到账银行卡尾号后四位
        //申请借款界面银行卡下面的小贴士(参考的老系统)
        resultMap.put("tips","您将在" + period + "天后还款" + applyMoney+ "元");//多少天后还款
        resultMap.put("flag","0");//借款允许的标记
        //把判断完成允许借款的申请数据放入一份进入Redis中，作为用户在申请界面提交申请后传入的参数的一个校验，防止申请过程中被恶意修改借款金额
        String applyLoanData = JSON.toJSONString(resultMap);
        redisUtil.del(Constant.REDIS_LOAN_DATA_PREFIX+userInfo.getPhone()+userInfo.getId());
        redisUtil.set(Constant.REDIS_LOAN_DATA_PREFIX+userInfo.getPhone()+userInfo.getId(),applyLoanData,Constant.LOAN_DATA_EXPIRATION_TIME);
        if (redisUtil.hasKey(Constant.REDIS_LOAN_DATA_PREFIX+userInfo.getPhone()+userInfo.getId())){
            return new CallBackResult(CallBackResult.SUCCESS,"允许申请借款 ",resultMap);
        }else {
            return new CallBackResult(Constant.RESULT_BAD_STATUS,"数据丢失，请稍后再试");
        }
    }

    /**
     * 保存订单号，订单生成成功后并进入风控（消息队列中）
     * @param newUserInfo       //通过token在Redis中取出的用户在数据库查出来的新用户信息
     * @param redisLoanDatas    //判断借款条件时的Redis中的借款数据信息
     * @param applyMoney        //申请金额
     * @param loanFee            //服务费
     * @param period              //借款期限
     * @param userBankCardInfo    //用户银行卡信息
     * @param resultPwdStatus     //返回给APP是否有密码的标记
     * @return
     */
    public Object saveLoanOrder(UserInfo newUserInfo,Map<String,Object> redisLoanDatas,Integer applyMoney,Integer loanFee,Integer period,UserBankCardInfo userBankCardInfo,Map<String,Object> resultPwdStatus){
        log.info("start invoke UserLoanController  confirmLoan newUserInfo={},redisLoanDatas={},applyMoney={},loanFee={},period={},userBankCardInfo={},resultPwdStatus={}",newUserInfo.toString(),redisLoanDatas.toString(),applyMoney,loanFee,period,userBankCardInfo,resultPwdStatus);
        OrderBorrow orderBorrow = new OrderBorrow();
        orderBorrow.setUserId(newUserInfo.getId());  //用户id
        Double apr_fee = Double.parseDouble(redisLoanDatas.get("apr_Fee").toString());
        apr_fee = apr_fee * Constant.ARP_FEE; //费率乘10000转换为分
        orderBorrow.setFeeApr(apr_fee.shortValue() );//用户服务费率
        orderBorrow.setApplyAmount((applyMoney * Constant.DOLLAR_CHANGE_PENNY));//申请金额（传入值的单位：分）
        orderBorrow.setLoanFee(loanFee * Constant.DOLLAR_CHANGE_PENNY);//借款服务费
        orderBorrow.setCreateTime(new Date());//创建时间
        orderBorrow.setUpdateTime(new Date());//更新时间
        orderBorrow.setLoanTerm(period); //借款的期限v1.0版本目前默认按天算（后期若有改动：需要APP用户选择方式传入参数来定具体单位借款的类型('0:按天，1,：按月，2：按年')和借款期限的单位(几天、几月、几年)）
        orderBorrow.setIntoMoney((applyMoney-loanFee) * Constant.DOLLAR_CHANGE_PENNY);//实际到账金额（总的金额减服务费）* 100 转换为分
        orderBorrow.setBankCardId(userBankCardInfo.getId());//设置银行卡id
        orderBorrow.setOutTradeNo(GenerateNo.nextOrdId()); //生成第三方订单流水号（暂时参考的老系统,如果这里没有生成，因数据库字段唯一性，再次生成一个订单时会报错）
        int statues = orderBorrowService.insertSelective(orderBorrow);
        if (statues > 0){//还需放入消息队列中进行风控处理，并返回进度
            resultPwdStatus.put("payPwdStatus","1");//有交易密码的状态
            return  new CallBackResult(CallBackResult.SUCCESS,"申请成功",resultPwdStatus);
        }else {
            return  new CallBackResult(Constant.RESULT_BAD_STATUS,"申请失败");
        }
    }
}
